﻿using System;
using System.Collections.Generic;
using System.Linq;
using GigaSite.Domain.Entities;
using GigaSite.Domain.Enums;
using GigaSite.Domain.Infrastucture.Misc;
using GigaSite.Domain.Interfaces.Repositories;

namespace GigaSite.Domain.DAL.Repositories
{
    public class UsersRepository: BaseRepository<User>, IUsersRepository
    {
        /// <summary>
        /// Базовый конструктор
        /// </summary>
        /// <param name="dataContext"></param>
        public UsersRepository(GigaDataContext dataContext) : base(dataContext)
        {
        }

        /// <summary>
        /// Загружает указанную сущность по ее идентификатору
        /// </summary>
        /// <param name="id">Идентификатор сущности</param>
        /// <returns>Сущность с указанным идентификатором или Null</returns>
        public override User Load(long id)
        {
            return Find(u => u.Id == id);
        }

        /// <summary>
        /// Получает пользователя по уникальному идентификатору-логину
        /// </summary>
        /// <param name="identity">Идентити</param>
        /// <returns>Пользователь или null если его не найдено</returns>
        public User GetUserByIdentity(string identity)
        {
            return Find(u => u.Identity == identity);
        }

        /// <summary>
        /// Извлекает из базы пользователя с указанным логином и хешем
        /// </summary>
        /// <param name="identity">Логин</param>
        /// <param name="password">Хеш пароля</param>
        /// <returns>Пользователь</returns>
        public User GetUserByIdentityAndPasswordHash(string identity, string password)
        {
            return Find(u => u.Identity == identity && u.Password == password);
        }

        /// <summary>
        /// Получает всех заблокированных пользователей
        /// </summary>
        /// <returns>Коллекция заблокированных пользователей</returns>
        public IEnumerable<User> GetBlockedUsers()
        {
            return Search(u => u.Blocked);
        }

        /// <summary>
        /// Регистрирует пользователя по его данным из социальных сетей
        /// </summary>
        /// <param name="json">Содержащий сведения, пришедшие от логинзы</param>
        /// <returns>Новый пользователь</returns>
        public User RegisterUser(string json)
        {
            // Инициализируем объект
            dynamic jsonObject = new DynamicJsonObject(json);

            // Извлекаем самые основные данные
            string identity = jsonObject.identity;
            string provider = jsonObject.provider;

            // Остальные поля
            string nickname = null, email = null, firstname = null, lastname = null, surname = null, photo = null, website = null;
            DateTime? birthday;
            UserGender gender = UserGender.DontKnow;

            // Пытаемся извлечь остальные поля
            if (jsonObject.nickname != null)
            {
                nickname = jsonObject.nickname;
            }
            if (jsonObject.email != null)
            {
                email = jsonObject.email;
            }
            if (jsonObject.gender != null)
            {
                string g = null;
                g = jsonObject.gender;
                switch (g)
                {
                    case "F":
                        gender = UserGender.Female;
                        break;
                    case "M":
                        gender = UserGender.Male;
                        break;
                    default:
                        gender = UserGender.DontKnow;
                        break;
                }
            }
            if (jsonObject.name != null)
            {
                if (jsonObject.name.first_name != null)
                {
                    firstname = jsonObject.name.first_name;
                }
                if (jsonObject.name.last_name != null)
                {
                    lastname = jsonObject.name.last_name;
                }
                if (jsonObject.name.middle_name != null)
                {
                    surname = jsonObject.name.middle_name;
                }
            }
            if (jsonObject.photo != null)
            {
                photo = jsonObject.photo;
            }
            if (jsonObject.web != null)
            {
                /*if (jsonObject.web["default"] != null)
                {
                    website = jsonObject.web["default"];
                }*/
                // TODO: научиться извлекать
            }
            if (jsonObject.dob != null)
            {
                DateTime parsedDate;
                string dob = jsonObject.dob;
                if (DateTime.TryParse(dob,out parsedDate))
                {
                    birthday = parsedDate;
                }
                else
                {
                    birthday = null;
                }
            }
            else
            {
                birthday = null;
            }

            // Создаем нового пользователя и присваиваем всю информацию что смогли извлечь
            var newUser = new User
                              {
                                  Access = (int) AccessLevels.StandartUser,
                                  AvatarURL = photo,
                                  Birthday = birthday,
                                  Blocked = false,
                                  City = "Хабаровск",
                                  // TODO: пока что все пользователи создаются в городе Хабаровске
                                  Description = null,
                                  DateCreated = DateTime.Now,
                                  Email = email,
                                  FirstName = firstname,
                                  Gender = gender,
                                  Identity = identity,
                                  IdentityProvider = provider,
                                  LastName = lastname,
                                  Nickname = nickname,
                                  SurName = surname,
                                  SocialAuthData = json,
                                  Password = PasswordUtils.GenerateMD5PasswordHash(PasswordUtils.GeneratePassword(9)),
                                  WebSite = website
                              };
            Add(newUser);

            // отдаем пользователя
            return newUser;
        }

        /// <summary>
        /// Регистрирует нового пользователя с указанным логином и паролем
        /// </summary>
        /// <param name="userName">Имя пользователя</param>
        /// <param name="email">Email пользователя</param>
        /// <param name="password">Пароль</param>
        /// <returns>Созданный пользователя</returns>
        public User RegisterUser(string userName, string email, string password)
        {
            // Просто создаем пользователя
            var newUser = new User()
                              {
                                  Access = (int) AccessLevels.StandartUser,
                                  City = "Хабаровск",
                                  // TODO: пока что все пользователя создаются в Хабаровске
                                  Identity = userName,
                                  IdentityProvider = "gigasite",
                                  DateCreated = DateTime.Now,
                                  Email = email,
                                  Blocked = false,
                                  Nickname = userName,
                                  Password = PasswordUtils.GenerateMD5PasswordHash(password)
                              };
            Add(newUser);

            return newUser;
        }

        /// <summary>
        /// Обновляет данные пользователя на основе информации из социальных сетей
        /// </summary>
        /// <param name="user">Пользователь</param>
        /// <param name="json">Данные о пользователе в json формате</param>
        public void UpdateUserSocialData(User user, string json)
        {
            // Инициализируем объект
            dynamic jsonObject = new DynamicJsonObject(json);

            // Поля
            string nickname = null, email = null, gender = null, firstname = null, lastname = null, surname = null, photo = null, website = null;
            DateTime? birthday;

            // Пытаемся извлечь остальные поля
            if (jsonObject.nickname != null)
            {
                nickname = jsonObject.nickname;
            }
            if (jsonObject.email != null)
            {
                email = jsonObject.email;
            }
            if (jsonObject.gender != null)
            {
                gender = jsonObject.gender;
            }
            if (jsonObject.name != null)
            {
                if (jsonObject.name.first_name != null)
                {
                    firstname = jsonObject.name.first_name;
                }
                if (jsonObject.name.last_name != null)
                {
                    lastname = jsonObject.name.last_name;
                }
                if (jsonObject.name.middle_name != null)
                {
                    surname = jsonObject.name.middle_name;
                }
            }
            if (jsonObject.photo != null)
            {
                photo = jsonObject.photo;
            }
            if (jsonObject.web != null)
            {
                if (jsonObject.web["default"] != null)
                {
                    website = jsonObject.web["default"];
                }
            }
            if (jsonObject.dob != null)
            {
                DateTime parsedDate;
                string dob = jsonObject.dob;
                if (DateTime.TryParse(dob, out parsedDate))
                {
                    birthday = parsedDate;
                }
                else
                {
                    birthday = null;
                }
            }
            else
            {
                birthday = null;
            }

            // Обновляем пользователя если пришедшие данные не null
            if (nickname != null)
            {
                user.Nickname = nickname;
            }
            if (email != null)
            {
                user.Email = email;
            }
            if (gender != null)
            {
                switch (gender)
                {
                    case "F":
                        user.Gender = UserGender.Female;
                        break;
                    case "M":
                        user.Gender = UserGender.Male;
                        break;
                }
            }
            if (firstname != null)
            {
                user.FirstName = firstname;
            }
            if (lastname != null)
            {
                user.LastName = lastname;
            }
            if (surname != null)
            {
                user.SurName = surname;
            }
            if (photo != null)
            {
                user.AvatarURL = photo;
            }
            if (website != null)
            {
                user.WebSite = website;
            }
            user.SocialAuthData = json;
        }
    }
}